<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>The root window</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Cairo, graphics, C, 2D vector library, 
root window, desktop window">
<meta name="description" content="In this chapter of the Cairo graphics tutorial, we will
have examples that work with the root window.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Root window</h1>


<p>
In this part of the Cairo graphics tutorial, we will work with the root window. 
The root window is the desktop window where we usually have icon shortcuts.
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script>

<p>
It is possible to manipulate with the root window. From the programmer's perspective,
it is just a special kind of a window. 
</p>


<h2>Transparent window</h2>

<p>
Our first example will create a transparent window. We will see, what it beneath
of the window object. 
</p>

<pre class="code">
#include &lt;cairo.h&gt;
#include &lt;gtk/gtk.h&gt;

static void do_drawing(cairo_t *);


static void tran_setup(GtkWidget *win)
{        
  GdkScreen *screen;
  GdkVisual *visual;
  
  gtk_widget_set_app_paintable(win, TRUE);
  screen = gdk_screen_get_default();
  visual = gdk_screen_get_rgba_visual(screen);
  
  if (visual != NULL &amp;&amp; gdk_screen_is_composited(screen)) {
      gtk_widget_set_visual(win, visual);
  }
}

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, 
    gpointer user_data)
{      
  cr = gdk_cairo_create(gtk_widget_get_window(widget));
  do_drawing(cr);  
  cairo_destroy(cr);

  return FALSE;
}

static void do_drawing(cairo_t *cr)
{
  cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 0.4);
  cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
  cairo_paint(cr);
}

int main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *darea;

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  
  tran_setup(window);

  darea = gtk_drawing_area_new();
  gtk_container_add(GTK_CONTAINER (window), darea);

  g_signal_connect(G_OBJECT(darea), "draw", 
      G_CALLBACK(on_draw_event), NULL); 
  g_signal_connect(window, "destroy",
      G_CALLBACK(gtk_main_quit), NULL);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 250); 
  gtk_window_set_title(GTK_WINDOW(window), "Transparent window");

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
To create a transparent window, we get the visual of the screen object
and set it for our window. In the on_draw() method, we draw over the
screen's visual object. This createas an illusion of partial transparency.
</p>

<pre class="explanation">
gtk_widget_set_app_paintable(win, TRUE);
</pre>

<p>
We must set the application to be painted on.
</p>

<pre class="explanation">
screen = gdk_screen_get_default();
</pre>

<p>
The <code>gdk_screen_get_default()</code> method returns the screen object.
</p>

<pre class="explanation">
visual = gdk_screen_get_rgba_visual(screen);
</pre>

<p>
From the screen window, we get its visual. The visual contains the low level
display information.
</p>

<pre class="explanation">
if (visual != NULL &amp;&amp; gdk_screen_is_composited(screen)) {
    gtk_widget_set_visual(win, visual);
}
</pre>

<p>
Not all displays support this operation. Therefore, we check if
our screen supports composition and the returned visual is not 
None. We set the screen's visual to be the visual of our window.
</p>

<pre class="explanation">
static void do_drawing(cairo_t *cr)
{
  cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 0.4);
  cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
  cairo_paint(cr);
}
</pre>

<p>
We use a partially transparent source to draw over the screen
window. The <code>CAIRO_OPERATOR_SOURCE</code> creates a composition
operation where we draw over the source. Which is the screen window.
To get full transparency, we set the alpha value to 0 or use the
<code>CAIRO_OPERATOR_CLEAR</code> operator.
</p>


<img src="/img/gfx/pycairo/trwindow.png" alt="Transparent window">
<div class="figure">Figure: Transparent window</div>


<h2>Taking a screenshot</h2>

<p>
The root window is also essential in taking a screenshot.
</p>

<pre class="code">
#include &lt;cairo.h&gt;
#include &lt;gdk/gdk.h&gt;

int main (int argc, char *argv[])
{
  gdk_init(&amp;argc, &amp;argv);
  
  GdkWindow *root_win = gdk_get_default_root_window();
  gint width = gdk_window_get_width(root_win);
  gint height = gdk_window_get_height(root_win);

  cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
      width, height);
    
  GdkPixbuf *pb = gdk_pixbuf_get_from_window(root_win, 0, 0, width, height);

  cairo_t *cr = cairo_create(surface);        
  gdk_cairo_set_source_pixbuf(cr, pb, 0, 0);  
  cairo_paint(cr);  

  cairo_surface_write_to_png(surface, "image.png");
  
  cairo_destroy(cr);
  cairo_surface_destroy(surface);

  return 0;
}
</pre>

<p>
The example captures a snapshot of the entire screen. In this example, we do not
use the full GTK windowing system. We use Cairo and GDK libraries to do the job.
</p>

<pre class="explanation">
gdk_init(&amp;argc, &amp;argv);
</pre>

<p>
The <code>gdk_init()</code> initializes the GDK library and connects to 
the windowing system.
</p>

<pre class="explanation">
GdkWindow *root_win = gdk_get_default_root_window();
</pre>

<p>
We get the root window with the <code>gdk_get_default_root_window()</code>
function call.
</p>

<pre class="explanation">
gint width = gdk_window_get_width(root_win);
gint height = gdk_window_get_height(root_win);
</pre>

<p>
We determine the width and the height of the root window.
</p>

<pre class="explanation">
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
    width, height);
</pre>

<p>
An empty image surface is created. It has the size of the root 
window.
</p>

<pre class="explanation">
GdkPixbuf *pb = gdk_pixbuf_get_from_window(root_win, 0, 0, width, height);
</pre>

<p>
We get a pixbuf from the root window using the <code>gdk_pixbuf_get_from_window()</code>
function call. A pixbuf is an object that describes an image in memory. 
</p>

<pre class="explanation">
cairo_t *cr = cairo_create(surface);        
gdk_cairo_set_source_pixbuf(cr, pb, 0, 0);  
cairo_paint(cr);
</pre>

<p>
In the above code lines, we create a Cairo drawing context on the
image surface that we have created earlier. We place the pixbuf
on the drawing context and paint it on the surface. 
</p>

<pre class="explanation">
cairo_surface_write_to_png(surface, "image.png");
</pre>

<p>
The image surface is written to a PNG image using the
<code>write_to_png()</code> method.
</p>

<pre class="explanation">
cairo_destroy(cr);
cairo_surface_destroy(surface);
</pre>

<p>
We clean up resources.
</p>


<h2>Showing a message</h2>

<p>
In the third example, we will show a message on the desktop window.
</p>

<pre class="code">
#include &lt;cairo.h&gt;
#include &lt;gtk/gtk.h&gt;
#include &lt;pango/pango.h&gt;

static void do_drawing(cairo_t *);

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, 
    gpointer user_data)
{      
  cr = gdk_cairo_create(gtk_widget_get_window(widget));
  do_drawing(cr);  
  cairo_destroy(cr);

  return FALSE;
}

static void do_drawing(cairo_t *cr)
{
   cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
   cairo_paint(cr);
   cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
}

static void setup(GtkWidget *win)
{        
  gtk_widget_set_app_paintable(win, TRUE);
  gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_DOCK);
  gtk_window_set_keep_below(GTK_WINDOW(win), TRUE);
  
  GdkScreen *screen = gdk_screen_get_default();
  GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
  
  if (visual != NULL &amp;&amp; gdk_screen_is_composited(screen)) {
      gtk_widget_set_visual(win, visual);
  }  
}

int main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *lbl;

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  
  setup(window);
  
  lbl = gtk_label_new("ZetCode, tutorials for programmers");
  
  PangoFontDescription *fd = pango_font_description_from_string("Serif 20");
  gtk_widget_modify_font(lbl, fd);  
  gtk_container_add(GTK_CONTAINER(window), lbl);  
  
  GdkColor color;
  gdk_color_parse("white", &amp;color);
  gtk_widget_modify_fg(lbl, GTK_STATE_NORMAL, &amp;color);
  
  g_signal_connect(G_OBJECT(window), "draw", 
      G_CALLBACK(on_draw_event), NULL); 
  g_signal_connect(window, "destroy",
      G_CALLBACK(gtk_main_quit), NULL);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 350, 250); 

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
The code displays a message label on the root window. 
</p>

<pre class="explanation">
static void do_drawing(cairo_t *cr)
{
   cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
   cairo_paint(cr);
   cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
}
</pre>

<p>
We use the <code>CAIRO_OPERATOR_CLEAR</code> operator to clear
the background of the window. Then we set the <code>CAIRO_OPERATOR_OVER</code>
to let the label widget be drawn. 
</p>

<pre class="explanation">
gtk_widget_set_app_paintable(win, TRUE);
</pre>

<p>
We will be manipulating the application window, so we make it paintable.
</p>

<pre class="explanation">
gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_DOCK);
</pre>

<p>
Implementing this window hint removes window borders and
decoration.
</p>

<pre class="explanation">
gtk_window_set_keep_below(GTK_WINDOW(win), TRUE);
</pre>

<p>
We keep the application always at the bottom, just over the root window.
</p>

<pre class="explanation">
GdkScreen *screen = gdk_screen_get_default();
GdkVisual *visual = gdk_screen_get_rgba_visual(screen);

if (visual != NULL &amp;&amp; gdk_screen_is_composited(screen)) {
    gtk_widget_set_visual(win, visual);
  } 
</pre>

<p>
We set the visual of the screen to be the visual of our application.
</p>

<pre class="explanation">
lbl = gtk_label_new("ZetCode, tutorials for programmers");
</pre>

<p>
We create a message label. 
</p>

<pre class="explanation">
PangoFontDescription *fd = pango_font_description_from_string("Serif 20");
gtk_widget_modify_font(lbl, fd);  
</pre>

<p>
With the help of the Pango module, we select a specific font for the text.
</p>

<pre class="explanation">
gtk_container_add(GTK_CONTAINER(window), lbl);   
</pre>

<p>
The label is put onto the window.
</p>

<pre class="explanation">
GdkColor color;
gdk_color_parse("white", &amp;color);
gtk_widget_modify_fg(lbl, GTK_STATE_NORMAL, &amp;color);
</pre>

<p>
We modify the text to be in white colour.
</p>

<img src="/img/gfx/cairoc/desktopwrite.png" alt="Message on the root window">
<div class="figure">Figure: Message on the root window</div>


<p>
In this chapter we have worked with the desktop window in Cairo.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified December 12, 2012 <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
